package com.crane.oss.sys.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crane.oss.sys.dao.MenuApiDao;
import com.crane.oss.sys.dao.RoleDao;
import com.crane.oss.sys.dao.RoleMenuDao;
import com.crane.oss.sys.model.MenuApi;
import com.crane.oss.sys.model.Role;
import com.crane.oss.sys.model.RoleMenu;
import com.crane.oss.sys.service.RoleMenuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service("roleMenuService")
public class RoleMenuServiceImpl extends ServiceImpl<RoleMenuDao, RoleMenu> implements RoleMenuService {

    private static final Logger logger = LoggerFactory.getLogger(RoleMenuServiceImpl.class);

    @Resource
    protected RoleMenuDao roleMenuDao;

    @Resource
    protected RoleDao roleDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatch(Long roleId, Long userId, List<Long> menuIdList) {
        logger.info("RoleMenuServiceImpl saveBatch roleId={},userId={},menuIdList={}", roleId, userId, menuIdList);
        if (menuIdList.size() == 0) {
            return;
        }
        // 去重
        Set<Long> menuIdSet = new HashSet<>(menuIdList);
        List<Long> list = new ArrayList<>();
        list.addAll(menuIdSet);

        // 保存角色与菜单关系
        List<RoleMenu> roleMenuList = new ArrayList<>();
        for (Long menuId : list) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menuId);
            roleMenu.setCreateTime(new Date());
            roleMenu.setCreateUserId(userId);
            roleMenuList.add(roleMenu);
        }
        this.saveBatch(roleMenuList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBatch(Long roleId, Long userId, List<Long> menuIdList) {
        logger.info("RoleMenuServiceImpl updateBatch roleId={},userId={},menuIdList={}", roleId, userId, menuIdList);
        if (menuIdList.size() == 0) {
            return;
        }
        // 删除当前角色菜单
        roleMenuDao.delete(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu ::getRoleId,roleId));
        this.saveBatch(roleId, userId, menuIdList);
        // 删除子角色的菜单权限
        updateChildBatch(roleId, menuIdList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByRoleId(Long roleId) {
        logger.info("RoleMenuServiceImpl deleteByRoleId roleId={}", roleId);
        roleMenuDao.delete(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu ::getRoleId,roleId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByMenuId(Long menuId) {
        logger.info("RoleMenuServiceImpl deleteByMenuId menuId={}", menuId);
        roleMenuDao.delete(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu ::getMenuId,menuId));
    }

    private void updateChildBatch(Long roleId, List<Long> menuIdList) {
        if (menuIdList.size() == 0) {
            return;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("parentId", roleId);
        List<Role> roleLs = roleDao.selectList(Wrappers.lambdaQuery(Role.class).eq(Role ::getParentId,roleId));
        if (roleLs.size() == 0) {
            return;
        } else {
            for (Role role : roleLs) {
                compareMenu(menuIdList, role);
                updateChildBatch(role.getId(), menuIdList);
            }
        }
    }

    /**
     * 比较当前角色菜单和修改菜单比较
     *
     * @param menuIdList 修改菜单id
     * @param role       已存在的角色
     */
    private void compareMenu(List<Long> menuIdList, Role role) {
        List<RoleMenu> roleMenuList = roleMenuDao.selectList(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu::getRoleId,role.getId()));
        for (RoleMenu roleMenu : roleMenuList) {
            if (!menuIdList.contains(roleMenu.getMenuId())) {
                roleMenuDao.delete(Wrappers.lambdaQuery(RoleMenu.class).eq(RoleMenu ::getMenuId,(roleMenu.getMenuId())).eq(RoleMenu ::getRoleId,role.getId()));
            }
        }
    }

}
